package org.wutopia.labcloud.domain.payment.service.Impl.dubbo;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboService;
import org.apache.seata.rm.tcc.api.BusinessActionContext;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.wutopia.labcloud.domain.payment.constant.PaymentChannelType;
import org.wutopia.labcloud.domain.payment.constant.PaymentOrderType;
import org.wutopia.labcloud.domain.payment.constant.WalletBillType;
import org.wutopia.labcloud.domain.payment.dao.PaymentOrderBillDao;
import org.wutopia.labcloud.domain.payment.dao.PaymentUserWalletBillDao;
import org.wutopia.labcloud.domain.payment.dao.PaymentUserWalletDao;
import org.wutopia.labcloud.domain.payment.dao.entity.PaymentOrderBill;
import org.wutopia.labcloud.domain.payment.dao.entity.PaymentUserWallet;
import org.wutopia.labcloud.domain.payment.dao.entity.PaymentUserWalletBill;
import org.wutopia.labcloud.service.api.service.seata.TccPaymentService;

import java.math.BigDecimal;


@DubboService
@AllArgsConstructor
@Slf4j
public class TccPaymentServiceImpl implements TccPaymentService {

    private PaymentUserWalletDao paymentUserWalletDao;

    private PaymentUserWalletBillDao paymentUserWalletBillDao;

    private PasswordEncoder passwordEncoder;

    private PaymentOrderBillDao paymentOrderBillDao;

    @Override
    public Long frozenMoney(BusinessActionContext actionContext, String payPassword, Long userId, Long orderId, BigDecimal frozen) throws Exception {

        // 1. 校验支付密码
        QueryWrapper<PaymentUserWallet> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId);
        PaymentUserWallet wallet = paymentUserWalletDao.selectOne(queryWrapper);

        boolean matches = passwordEncoder.matches(payPassword, wallet.getPayPassword());

        if(!matches) {
            throw new Exception("错误：密码错误");
        }

        // 2. 生成取出账单
        PaymentUserWalletBill bill = new PaymentUserWalletBill();
        bill.setMoney(frozen);
        bill.setUserId(userId);
        bill.setStatus(WalletBillType.WITHDRAWAL);
        bill.setChannelId(orderId);
        bill.setChannelType(PaymentChannelType.ORDER);
        bill.setUserWalletId(wallet.getId());
        paymentUserWalletBillDao.insert(bill);

        // 3. 冻结余额
        BigDecimal money = wallet.getMoney();
        if(money.compareTo(frozen) < 0) {
            throw new Exception("错误：余额不足");
        }
        wallet.setFrozen(wallet.getFrozen().add(frozen));
        wallet.setMoney(money.subtract(frozen));
        paymentUserWalletDao.updateById(wallet);

        // 4. 生成订单账单
        PaymentOrderBill orderBill = new PaymentOrderBill();
        orderBill.setOrderId(orderId);
        orderBill.setMoney(frozen);
        orderBill.setUserId(userId);
        orderBill.setUserWalletId(wallet.getId());
        orderBill.setStatus(PaymentOrderType.PAID);
        paymentOrderBillDao.insert(orderBill);

        return orderBill.getId();
    }

    @Override
    public boolean moneyCommit(BusinessActionContext actionContext) {
        return true;
    }

    @Override
    public boolean moneyCancel(BusinessActionContext actionContext) throws Exception {

        BigDecimal frozen = actionContext.getActionContext("frozen", BigDecimal.class);
        Long orderId = actionContext.getActionContext("orderId", Long.class);
        Long userId = actionContext.getActionContext("userId", Long.class);
        // 1. 还回冻结余额
        QueryWrapper<PaymentUserWallet> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId);
        PaymentUserWallet wallet = paymentUserWalletDao.selectOne(queryWrapper);

        BigDecimal oldFrozen = wallet.getFrozen();
        if(oldFrozen.compareTo(frozen) < 0) {
            throw new Exception("错误：冻结余额少于需要还原的余额");
        }
        wallet.setFrozen(wallet.getFrozen().subtract(frozen));
        wallet.setMoney(wallet.getMoney().subtract(frozen));
        paymentUserWalletDao.updateById(wallet);

        // 2. 删除支付账单
        QueryWrapper<PaymentUserWalletBill> q = new QueryWrapper<>();
        q.eq("user_id", userId);
        q.eq("user_wallet_id", wallet.getId());
        q.eq("channel_type", PaymentChannelType.ORDER);
        q.eq("channel_id", orderId);
        q.eq("money", frozen);
        q.eq("status", WalletBillType.WITHDRAWAL);
        paymentUserWalletBillDao.delete(q);


        // 3. 删除订单账单

        QueryWrapper<PaymentOrderBill> query = new QueryWrapper<>();
        query.eq("order_id", orderId);
        query.eq("user_id", userId);
        query.eq("user_wallet_id", wallet.getId());
        query.eq("money", frozen);
        query.eq("status", WalletBillType.WITHDRAWAL);
        paymentOrderBillDao.delete(query);

        return true;
    }



    @Override
    public boolean moneyReturn(BusinessActionContext actionContext, Long userId, Long orderId, BigDecimal frozen) throws Exception {

        // 1. 还回冻结余额
        QueryWrapper<PaymentUserWallet> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId);
        PaymentUserWallet wallet = paymentUserWalletDao.selectOne(queryWrapper);

        BigDecimal oldFrozen = wallet.getFrozen();
        if(oldFrozen.compareTo(frozen) < 0) {
            throw new Exception("错误：冻结余额少于需要还原的余额");
        }
        wallet.setFrozen(wallet.getFrozen().subtract(frozen));
        wallet.setMoney(wallet.getMoney().add(frozen));
        paymentUserWalletDao.updateById(wallet);

        // 2. 退回支付账单
        PaymentUserWalletBill bill = new PaymentUserWalletBill();
        bill.setMoney(frozen);
        bill.setUserId(userId);
        bill.setStatus(WalletBillType.DEPOSIT);
        bill.setChannelId(orderId);
        bill.setChannelType(PaymentChannelType.ORDER);
        bill.setUserWalletId(wallet.getId());
        paymentUserWalletBillDao.insert(bill);


        // 3. 修改订单账单状态为cancel

        UpdateWrapper<PaymentOrderBill> update = new UpdateWrapper<>();
        update.eq("order_id", orderId);
        update.eq("user_id", userId);
        update.eq("user_wallet_id", wallet.getId());
        update.eq("money", frozen);
        update.set("status", PaymentOrderType.CANCELED);
        paymentOrderBillDao.update(update);

        return true;
    }

    @Override
    public boolean returnConfirm(BusinessActionContext actionContext) {
        return false;
    }

    @Override
    public boolean returnCancel(BusinessActionContext actionContext) throws Exception {
        BigDecimal frozen = actionContext.getActionContext("frozen", BigDecimal.class);
        Long orderId = actionContext.getActionContext("orderId", Long.class);
        Long userId = actionContext.getActionContext("userId", Long.class);

        QueryWrapper<PaymentUserWallet> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId);
        PaymentUserWallet wallet = paymentUserWalletDao.selectOne(queryWrapper);

        // 还原订单账单状态为paid

        UpdateWrapper<PaymentOrderBill> update = new UpdateWrapper<>();
        update.eq("order_id", orderId);
        update.eq("user_id", userId);
        update.eq("user_wallet_id", wallet.getId());
        update.eq("money", frozen);
        update.set("status", PaymentOrderType.PAID);
        paymentOrderBillDao.update(update);

        // 删除退回账单
        QueryWrapper<PaymentUserWalletBill> q = new QueryWrapper<>();
        q.eq("user_id", userId);
        q.eq("user_wallet_id", wallet.getId());
        q.eq("channel_type", PaymentChannelType.ORDER);
        q.eq("channel_id", orderId);
        q.eq("money", frozen);
        q.eq("status", WalletBillType.DEPOSIT);
        paymentUserWalletBillDao.delete(q);

        // 复原金额为冻结金额
        BigDecimal oldMoney = wallet.getMoney();
        if(oldMoney.compareTo(frozen) < 0) {
            throw new Exception("错误：冻结余额少于需要还原的余额");
        }
        wallet.setFrozen(wallet.getFrozen().add(frozen));
        wallet.setMoney(wallet.getMoney().subtract(frozen));
        paymentUserWalletDao.updateById(wallet);

        return true;
    }

    @Override
    public boolean frozenRelease(BusinessActionContext actionContext, Long userId, Long orderId, BigDecimal frozen) throws Exception {
        // 1. 释放冻结金额
        QueryWrapper<PaymentUserWallet> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId);
        PaymentUserWallet wallet = paymentUserWalletDao.selectOne(queryWrapper);

        BigDecimal oldFrozen = wallet.getFrozen();
        if(oldFrozen.compareTo(frozen) < 0) {
            throw new Exception("错误：冻结余额少于需要还原的余额");
        }
        wallet.setFrozen(wallet.getFrozen().subtract(frozen));
        paymentUserWalletDao.updateById(wallet);



        return true;
    }

    @Override
    public boolean frozenReleaseConfirm(BusinessActionContext actionContext) {
        return true;
    }

    @Override
    public boolean frozenReleaseCancel(BusinessActionContext actionContext) throws Exception {
        BigDecimal frozen = actionContext.getActionContext("frozen", BigDecimal.class);
        Long orderId = actionContext.getActionContext("orderId", Long.class);
        Long userId = actionContext.getActionContext("userId", Long.class);

        // 1. 回退释放冻结金额
        QueryWrapper<PaymentUserWallet> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId);
        PaymentUserWallet wallet = paymentUserWalletDao.selectOne(queryWrapper);


        wallet.setFrozen(wallet.getFrozen().add(frozen));
        paymentUserWalletDao.updateById(wallet);


        return true;
    }
}
